home *** CD-ROM | disk | FTP | other *** search
- /* $Header: uucp.c,v 2.6 90/05/03 10:35:51 chip Exp $
- *
- * Handle mail destined for other hosts via UUCP.
- * Deliver is intended as a very low-level program, so we don't
- * do anything fancy here. We just hand the message to uux.
- *
- * $Log: uucp.c,v $
- * Revision 2.6 90/05/03 10:35:51 chip
- * Quiet lint.
- *
- * Revision 2.5 90/05/03 10:26:21 chip
- * Combine destinations with a common first hop.
- *
- * Revision 2.4 90/02/23 14:16:54 chip
- * Support "#!" in delivery files.
- * Support "user|program" and "user?error" from delivery files.
- * Improve debugging and error message formatting.
- * Rearrange code for clarity.
- *
- * Revision 2.3 89/12/19 16:26:41 network
- * Execute UUCP in real, not effective, context.
- * This allows users to cancel their UUCP jobs.
- *
- * Revision 2.2 89/11/01 12:31:17 network
- * Use the new exists() function.
- *
- * Revision 2.1 89/06/09 12:25:44 network
- * Update RCS revisions.
- *
- * Revision 1.5 89/06/09 12:24:02 network
- * Baseline for 2.0 release.
- *
- */
-
- #include "deliver.h"
-
- /*
- * Local functions.
- */
-
- static char *find_uux();
- static int uucp_copy();
-
- /*----------------------------------------------------------------------
- * Send mail to UUCP addresses (if any).
- * Return count of UUCP addresses for which delivery was attempted.
- */
-
- int
- uucp_deliver()
- {
- DEST *d;
- char *uav[UUX_ARGCOUNT + 8]; /* arguments for execv() */
- char **av; /* remote addresses in uav[] */
- DEST *dv[UUX_ARGCOUNT]; /* destinations in av[] */
- char rmail[UUCP_NAMESIZE + 8]; /* "sysname!rmail" */
- char *uux;
- int uucpcount;
-
- if ((uux = find_uux()) == NULL)
- return -1;
-
- av = uav;
- *av++ = "uux";
- #ifdef UUX_OPTS
- *av++ = UUX_OPTS;
- #endif
- *av++ = "-";
- *av++ = rmail;
-
- /*
- * Look for a UUCP address that is "working". If we find one,
- * then we scan the rest of the list for other UUCP addresses
- * that begin with the same first hop. If we find any, then
- * we handle them too. Note that as we continue scanning,
- * we'll find those same addresses again; that's okay, though,
- * because their status fields will report that they're
- * already done. Cool, eh?
- */
-
- uucpcount = 0;
-
- for (d = first_dest(); d; d = next_dest(d))
- {
- FILE *uux_fp;
- DEST *ud;
- DERROR e;
- char *bang;
- int namesize, argcount, argsize, problem, a;
-
- if (d->d_class != CL_UUCP || d->d_state != ST_WORKING)
- continue;
-
- ++uucpcount;
-
- if (printaddrs)
- (void) printf("%s\n", d->d_name);
-
- if (dryrun)
- {
- d->d_state = ST_DONE;
- continue;
- }
-
- /*
- * This is the first destination with the given system
- * as the first hop. Generate the rmail command.
- */
-
- if ((bang = strchr(d->d_name, '!')) == NULL
- || (namesize = bang - d->d_name) > UUCP_NAMESIZE)
- {
- dest_err(d, E_NSHOST);
- continue;
- }
-
- (void) strncpy(rmail, d->d_name, namesize);
- (void) strcpy(rmail + namesize, "!rmail");
-
- /*
- * Now keep looking for addresses until a limit is reached,
- * either max arguments or max argument size.
- * We'll find them again, but their statuses will prevent us
- * from trying to mail to them twice.
- */
-
- argcount = 0;
- argsize = 0;
- for (ud = d; ud; ud = next_dest(ud))
- {
- char *rest, *arg;
-
- if (ud->d_class != CL_UUCP
- || ud->d_state != ST_WORKING)
- continue;
-
- if (strncmp(ud->d_name, d->d_name, namesize + 1) != 0)
- continue;
-
- /*
- * We have a match! (Or, it could be the first one.)
- * Be sure we don't exceed our configured maxima,
- * except for the first address, which always goes.
- */
-
- rest = ud->d_name + namesize + 1;
-
- if (argcount > 0)
- {
- if (argcount + 1 > UUX_ARGCOUNT
- || argsize + strlen(rest) + 2 > UUX_ARGSIZE)
- break;
- }
-
- /*
- * Generate a uux argument and save the destination.
- */
-
- arg = zalloc((unsigned) 3 + strlen(rest));
- (void) sprintf(arg, "(%s)", rest);
-
- av[argcount] = arg;
- dv[argcount] = ud;
-
- /*
- * Keep track of arg count and total size.
- */
-
- ++argcount;
- argsize += strlen(arg);
- }
-
- av[argcount] = NULL;
-
- /*
- * Do the dirty deed.
- * We have to remember the error code as a variable,
- * since it may apply to multiple destinations.
- */
-
- problem = 0;
- e = E_PIPE; /* default error */
-
- if ((uux_fp = ct_fopenv(real_ct, uux, uav, "w")) == NULL)
- problem = 1;
- else
- {
- if (uucp_copy(uux_fp) < 0)
- problem = 1;
-
- if (ct_fclose(uux_fp))
- {
- /* "No such host" overrides piping problems. */
- e = E_NSHOST;
- problem = 1;
- }
- }
-
- /*
- * We're done. Update each destination's status.
- */
-
- for (a = 0; a < argcount; ++a)
- {
- free(av[a]);
-
- if (problem)
- dest_err(dv[a], e);
- else
- dv[a]->d_state = ST_DONE;
- }
-
- /* Track the correct count of UUCP addresses found. */
-
- uucpcount += argcount - 1;
- }
-
- return uucpcount;
- }
-
- /*----------------------------------------------------------------------
- * Where is uux?
- */
-
- static char *
- find_uux()
- {
- static char uux1[] = "/bin/uux";
- static char uux2[] = "/usr/bin/uux";
-
- if (exists(uux1))
- return uux1;
- if (exists(uux2))
- return uux2;
- error("can't find uux!?\n");
- return NULL;
- }
-
- /*----------------------------------------------------------------------
- * Write the message for UUCP transmission to the given file.
- */
-
- static int
- uucp_copy(ofp)
- FILE *ofp;
- {
- FILE *ifp;
- char *p;
- register int c;
- int fd;
- char buf[BUFSIZ];
-
- if ((fd = dup(tfd[T_HDR])) == -1)
- {
- syserr("can't dup header fd");
- return -1;
- }
- (void) lseek(fd, 0L, 0);
- if ((ifp = fdopen(fd, "r")) == NULL)
- {
- error("can't fdopen header fd");
- return -1;
- }
-
- /*
- * Copy the header, but tack "remote from" onto the end of the
- * From_ line. (If it weren't for dealing with the From_ line,
- * I'd skip stream I/O altogether and use read/write. Maybe
- * I should save the length of the From_ line when I copy it...)
- */
-
- (void) fgets(buf, GETSIZE(buf), ifp);
- if ((p = strchr(buf, '\n')) != NULL)
- *p = 0;
- (void) fprintf(ofp, "%s remote from %s\n", buf, hostname);
-
- while ((c = getc(ifp)) != EOF)
- (void) putc(c, ofp);
-
- (void) fclose(ifp);
-
- /*
- * Copy the body
- */
-
- if ((fd = dup(tfd[T_BODY])) == -1)
- {
- syserr("can't dup body fd");
- return -1;
- }
- (void) lseek(fd, 0L, 0);
- if ((ifp = fdopen(fd, "r")) == NULL)
- {
- error("can't fdopen body fd");
- (void) close(fd);
- return -1;
- }
-
- while ((c = getc(ifp)) != EOF)
- (void) putc(c, ofp);
-
- (void) fclose(ifp);
- return 0;
- }
-